package cn.itsource.hrm.controller;


import cn.itsource.hrm.doc.CourseDoc;
import cn.itsource.hrm.query.CourseDocQuery;
import cn.itsource.hrm.repository.CourseDocRepository;
import cn.itsource.hrm.util.AggsVo;
import cn.itsource.hrm.util.AjaxResult;
import cn.itsource.hrm.util.PageList;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/courseDoc")
public class CourseDocController {

    @Autowired
    private CourseDocRepository courseDocRepository;
    //添加
    @PutMapping
    @PreAuthorize("hasAnyAuthority('courseDoc:add','courseDoc:update')")
    public AjaxResult addOrUpdateCourseDoc(@RequestBody CourseDoc courseDoc){

        try {
            courseDocRepository.save(courseDoc);
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("添加或修改课程文档失败！"+e.getMessage());
        }

    }

    //删除
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('courseDoc:delete')")
    public AjaxResult deleteCourseDoc(@PathVariable("id") Long id){
        try {
            courseDocRepository.deleteById(id);
            return AjaxResult.me();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("删除课程文档失败！"+e.getMessage());
        }
    }

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private SearchResultMapper searchResultMapper;
    //dsl=查询+过滤 select name,age from t_user where name =kjj orderby id desc limit 0,10
    /*
    * {
  "query": {
    "bool": {
      "must": [
        {
          "match_all": {}
        }
      ],
      "filter": {*/
    @PostMapping("/queryCourses")
    /**
     private Integer priceMin;
     private Integer priceMax;
     private String courseTypeName;
     private String tenantName;
     */

    public PageList<CourseDoc> queryPage(@RequestBody CourseDocQuery query){
        //创建一个查询构建器
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //一 构建查询条件
        BoolQueryBuilder boolQuery = buildQuery(query);
        builder.withQuery(boolQuery);// query-bool
        //二 高亮处理
        HighlightBuilder.Field field = new HighlightBuilder.Field("name")
                .preTags("<font style='color:red'>")
                .postTags("</font>");
        builder.withHighlightFields(field);

        //三 聚合处理 tenantNameAggs聚合名称 tenantName聚合字段  .order(Terms.Order.count(false))按照count做降序 size只去前20个
        builder.addAggregation(AggregationBuilders.terms("tenantNameAggs").field("tenantName")
                .order(Terms.Order.count(false)).size(20));
        builder.addAggregation(AggregationBuilders.terms("courseTypeNameAggs").field("courseTypeName")
                .order(Terms.Order.count(false)).size(20));
        // 3 排序
        if (!StringUtils.isEmpty(query.getSortField())){
            String sortField = query.getSortField();//jg-price xl-saleCount
            switch (sortField){
                case "jg":
                    sortField="price";
                    break;
                case "xl":
                    sortField="saleCount";
                    break;
            }

            String sortType = query.getSortType();//desc asc
            SortOrder sortOrder = SortOrder.DESC;
            if (!"desc".equals(sortType)){
                sortOrder = SortOrder.ASC;
            }
            //等会在转换
            builder.withSort(new FieldSortBuilder(sortField).order(sortOrder));
        }

        //4 分页
        //通过构建器构建一个查询对象

        NativeSearchQuery sQuery = builder.build();
        //通过查询对象进行分页查询
        //Page<CourseDoc> page = courseDocRepository.search(sQuery);
        AggregatedPage<CourseDoc> page = elasticsearchTemplate.queryForPage(sQuery, CourseDoc.class, searchResultMapper);

        //把聚合数据封装到PageList

        Map<String,List<AggsVo>> aggsVoData = new HashMap<>();
        StringTerms tenantNameAggs = (StringTerms) page.getAggregation("tenantNameAggs");
        List<StringTerms.Bucket> buckets = tenantNameAggs.getBuckets();
        List<AggsVo> tenantNameAggsVos = new ArrayList<>();
        buckets.forEach(bucket -> {
            //老面牌SPA(4)
            //源码时代(3)
            String key = bucket.getKeyAsString();
            long count = bucket.getDocCount();
            System.out.println(key+"("+count+")");
            tenantNameAggsVos.add(new AggsVo(key,count));

        });
        aggsVoData.put("tenantNameAggs",tenantNameAggsVos);
        StringTerms courseTypeNameAggs = (StringTerms) page.getAggregation("courseTypeNameAggs");
        System.out.println("=============================================");

        List<AggsVo> courseTypeNameAggsVos = new ArrayList<>();
        List<StringTerms.Bucket> buckets1 = courseTypeNameAggs.getBuckets();
        buckets1.forEach(bucket -> {
            String key = bucket.getKeyAsString();
            long count = bucket.getDocCount();
            System.out.println(key+"("+count+")");
            courseTypeNameAggsVos.add(new AggsVo(key,count));

        });
        aggsVoData.put("courseTypeNameAggs",courseTypeNameAggsVos);
        //把它的分页对象转换为我的分页对象
        return new PageList<>(page.getTotalElements(),page.getContent(),aggsVoData);
    }

    private BoolQueryBuilder buildQuery(@RequestBody CourseDocQuery query) {
        // 1 dsl查询-keyword
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (!StringUtils.isEmpty(query.getKeyword())){ //模糊 must should nustnot
            boolQuery.must(QueryBuilders.matchQuery("name", query.getKeyword())); //query-bool-must-match
//            boolQuery.should(QueryBuilders.matchQuery("tenantName", query.getKeyword())); //query-bool-must-match
//            boolQuery.should(QueryBuilders.matchQuery("courseTypeName", query.getKeyword())); //query-bool-must-match
//            boolQuery.should(QueryBuilders.matchQuery("forUser", query.getKeyword())); //query-bool-must-match
//            boolQuery.should(QueryBuilders.matchQuery("gradeName", query.getKeyword())); //query-bool-must-match
        }
        // 2 dsl过滤-courseTypeId courseTypeName tenantName  priceMin priceMax
        if (query.getCourseTypeId()!=null){//query-bool-filter 等值
            boolQuery.filter(QueryBuilders.termQuery("courseTypeId", query.getCourseTypeId()));
        }
        if (!StringUtils.isEmpty(query.getCourseTypeName()))
        {
            boolQuery.filter(QueryBuilders.termQuery("courseTypeName", query.getCourseTypeName()));
        }
        if (!StringUtils.isEmpty(query.getTenantName()))
        {
            boolQuery.filter(QueryBuilders.termQuery("tenantName", query.getTenantName()));
        }

        if (query.getPriceMin()!=null){ //我们的价格大于等于小的
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(query.getPriceMin()));
        }
        if (query.getPriceMax()!=null){ //我们的价格大于等于小的
            boolQuery.filter(QueryBuilders.rangeQuery("price").lte(query.getPriceMax()));
        }
        return boolQuery;
    }
}
